﻿#include "GUIGeometryRotateDialog.h"
#include "ui_GUIGeometryRotateDialog.h"
#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"
#include "FITK_Kernel/FITKCore/FITKOperatorRepo.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsGeometryData.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKGeoInterfaceFactory.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoModelOperLine.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeomTools.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoModelPoint.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoTransformation.h"


#include "PickDataProvider/GUIPickInfo.h"
#include "FITK_Kernel/FITKCore/FITKActionOperator.h"
#include "OperatorsInterface/GraphEventOperator.h"

#include "PickDataProvider/PickedData.h"
#include "PickDataProvider/PickedDataProvider.h"
#include "GraphDataProvider/GraphDataCalculate.h"
#include <QMessageBox>

namespace GUI {

    GUIGeometryRotateDialog::GUIGeometryRotateDialog(Core::FITKActionOperator* oper, QWidget* parent)
        : GUIGeometryBaseDialog(nullptr, oper, parent), _ui(new Ui::GUIGeometryRotateDialog)
    {
        _ui->setupUi(this);

        this->createGeometryObj(Interface::FITKGeoEnum::FITKGeometryComType::FGTRotate);
        this->init();
    }

    GUIGeometryRotateDialog::GUIGeometryRotateDialog(Interface::FITKAbsGeoModelSegment* obj, Core::FITKActionOperator* oper, QWidget* parent)
        : GUIGeometryBaseDialog(obj, oper, parent), _ui(new Ui::GUIGeometryRotateDialog)
    {
        _ui->setupUi(this);
        this->init();
    }

    GUIGeometryRotateDialog::~GUIGeometryRotateDialog()
    {
        if (_ui) {
            delete _ui;
            _ui = nullptr;
        }
    }

    void GUIGeometryRotateDialog::init()
    {
        setWindowTitle(tr("Rotate"));//旋转
        Acoustics::FITKAcousticsGeometryData* geometryData = FITKAPP->getGlobalData()->getGeometryData<Acoustics::FITKAcousticsGeometryData>();
        Interface::FITKAbsGeoModelRotate*roatetP = dynamic_cast<Interface::FITKAbsGeoModelRotate*>(_obj);
        if (roatetP == nullptr)return;
        if (geometryData == nullptr) return;

        //设置默认选择类型
        QVariant selectType(GUI::GUIPickInfo::POBJGeometryEdge);
        _ui->stretch_type->setProperty("selectType", selectType);

        //获取数据
        QString name = geometryData->checkName(tr("Curve-1"));
        if (!_isCreate) name = _obj->getDataObjectName();

        //设置界面
        _ui->lineEdit_Name->setText(name);
        //设置轴线起点初始化为0
        _ui->lineEdit_X->setText(QString::number(0));
        _ui->lineEdit_Y->setText(QString::number(0));
        _ui->lineEdit_Z->setText(QString::number(0));
        //设置轴线终点初始位0
        _ui->lineEdit_X_2->setText(QString::number(0));
        _ui->lineEdit_Y_2->setText(QString::number(0));
        _ui->lineEdit_Z_2->setText(QString::number(0));
        //设置旋转角度初始化为0
        _ui->lineEdit_Value->setText(QString::number(0));

        //旋转线面体，点不能旋转
        _ui->stretch_type->addItem("Curve");//线
        _ui->stretch_type->addItem("Surface");//面
        _ui->stretch_type->addItem("Solid");//体
    }

    QString GUIGeometryRotateDialog::getNameText()
    {
        return _ui->lineEdit_Name->text();
    }

    void GUIGeometryRotateDialog::pickFinishedOper()
    {
        //获取拾取数据
        GraphData::PickedDataProvider* provider = GraphData::PickedDataProvider::getInstance();
        if (provider == nullptr)return;
        disconnect(provider, SIGNAL(sig_pickedOver()), this, SLOT(slotPickOverEvent()));
        QList<GraphData::PickedData*> pickList = provider->getPickedList();
        Interface::FITKAbsGeoModelRotate*roatetP = dynamic_cast<Interface::FITKAbsGeoModelRotate*>(_obj);
        if (roatetP==nullptr)
        {
            return;
        }
        QList<Interface::VirtualShape> Shape;
        for (GraphData::PickedData* pickData : pickList) {
            if (pickData == nullptr)continue;
            int cmdID = pickData->getPickedDataObjId();
            QHash<int, int>OtherIDs = pickData->getPickedOtherIDs();
            for (int i : pickData->getPickedIds())
            {
                if (OtherIDs.contains(i) == true)
                {
                    Interface::VirtualShape temp(cmdID, i, OtherIDs.value(i));
                    Shape.push_back(temp);
                }
            }
        }
        //设置数据
        if (Shape.size() != 1)
        {
            return;
        }
        roatetP->setSourceShape(Shape.at(0));
    }

    void GUIGeometryRotateDialog::OnPickPoint1()
    {
        GraphData::PickedDataProvider* provider = GraphData::PickedDataProvider::getInstance();
        if (provider == nullptr)return;
        disconnect(provider, SIGNAL(sig_pickedOver()), this, SLOT(slotPickOverEvent()));
        QList<GraphData::PickedData*> pickList = provider->getPickedList();
        QList<int> idList = {};
        QList<int> PickedIds;
        for (GraphData::PickedData* pickData : pickList) {
            if (pickData == nullptr)continue;
            idList.append(pickData->getPickedDataObjId());
            PickedIds = pickData->getPickedIds();
        }
        //获取拾取的数据
        if (idList.isEmpty()) return;

        //根据id获取点的xyz
        std::array<double, 3> xyz = this->getPointXYZ(PickedIds.at(0));
        _ui->lineEdit_X->setText(QString::number(xyz.at(0), 'f', 7));
        _ui->lineEdit_Y->setText(QString::number(xyz.at(1), 'f', 7));
        _ui->lineEdit_Z->setText(QString::number(xyz.at(2), 'f', 7));
    }

    void GUIGeometryRotateDialog::OnPickPoint2()
    {
        GraphData::PickedDataProvider* provider = GraphData::PickedDataProvider::getInstance();
        if (provider == nullptr)return;
        disconnect(provider, SIGNAL(sig_pickedOver()), this, SLOT(slotPickOverEvent()));
        QList<GraphData::PickedData*> pickList = provider->getPickedList();
        QList<int> idList = {};
        QList<int> PickedIds;
        for (GraphData::PickedData* pickData : pickList) {
            if (pickData == nullptr)continue;
            idList.append(pickData->getPickedDataObjId());
            PickedIds = pickData->getPickedIds();
        }
        //获取拾取的数据
        if (idList.isEmpty()) return;

        //根据id获取点的xyz
        std::array<double, 3> xyz = this->getPointXYZ(PickedIds.at(0));
        _ui->lineEdit_X_2->setText(QString::number(xyz.at(0), 'f', 7));
        _ui->lineEdit_Y_2->setText(QString::number(xyz.at(1), 'f', 7));
        _ui->lineEdit_Z_2->setText(QString::number(xyz.at(2), 'f', 7));
    }

    void GUIGeometryRotateDialog::getDataFormWidget()
    {
        Interface::FITKAbsGeoModelRotate*roatetP = dynamic_cast<Interface::FITKAbsGeoModelRotate*>(_obj);
        if (roatetP == nullptr)
        {
            return;
        }
        roatetP->setCopy(true);
        roatetP->setCopy(false);
        //设置轴线起点
        double x = _ui->lineEdit_X->text().toDouble();
        double y = _ui->lineEdit_Y->text().toDouble();
        double z = _ui->lineEdit_Z->text().toDouble();
        roatetP->setAxisStartPoint(x, y, z);
        //设置轴线终点
        x = _ui->lineEdit_X_2->text().toDouble();
        y = _ui->lineEdit_Y_2->text().toDouble();
        z = _ui->lineEdit_Z_2->text().toDouble();
        roatetP->setAxisEndPoint(x, y, z);

        double angle = _ui->lineEdit_Value->text().toDouble();
        roatetP->setDegree(angle);
        roatetP->setDataObjectName(_ui->lineEdit_Name->text());//更新体名称
    }

    void GUIGeometryRotateDialog::OnpickInProcess()
    {
        //转换为string，拾取到的点的个数
        QString number = "(" + QString::number(m_pick_num) + ")";
        _ui->Pick_num->setText(number);
    }

    void GUIGeometryRotateDialog::on_stretch_type_activated(int item)
    {
        //在切换拾取模式后，将清空对3维的操作
        GraphData::PickedDataProvider* provider = GraphData::PickedDataProvider::getInstance();
        if (provider == nullptr)return;
        provider->clearPickedData();//清空拾取数据
        //拾取对象 关闭
        //拾取方式 空
        GUI::GUIPickInfoStru pickInfo = GUI::GUIPickInfo::GetPickInfo();
        pickInfo._pickObjType = GUI::GUIPickInfo::PickObjType(GUI::GUIPickInfo::POBJNone);
        pickInfo._pickMethod = GUI::GUIPickInfo::PickMethod(GUI::GUIPickInfo::PickMethod::PMNone);
        //设置拾取方式
        GUI::GUIPickInfo::SetPickInfo(pickInfo);

        ////清空界面拾取的个数显示，重新初始化为0
        _ui->Pick_num->setText("(0)");

        /*
        根据具体的选项，对创建对象的名称进行修改
        */
        Acoustics::FITKAcousticsGeometryData* geometryData = FITKAPP->getGlobalData()->getGeometryData<Acoustics::FITKAcousticsGeometryData>();
        if (geometryData == nullptr) return;


        QVariant selectType; 
        QString name = "";
        //选择要拾取的类型
        if (item == 0)
        {
            name = geometryData->checkName(tr("Curve-1"));
            selectType.setValue(GUI::GUIPickInfo::POBJGeometryEdge);
        }
        else if (item == 1)
        {
            name = geometryData->checkName(tr("Surface-1"));
            selectType.setValue(GUI::GUIPickInfo::POBJGeometryFace);
        }
        else if (item == 2)
        {
            name = geometryData->checkName(tr("Solid-1"));
            selectType.setValue(GUI::GUIPickInfo::POBJGeometrySolid);
        }
        //设置界面
        _ui->lineEdit_Name->setText(name);
        //设置当前选择
        _ui->stretch_type->setProperty("selectType", selectType);
    }

    void GUIGeometryRotateDialog::on_pushButton_Pick_clicked()
    {
        /*
        根据选择的模式，设置三维拾取方式
        */
        //获取存储的选择类型
        QVariant var = _ui->stretch_type->property("selectType");
        if (var.canConvert<GUI::GUIPickInfo::PickObjType>())
        {
            GUI::GUIPickInfo::PickObjType data2 = var.value<GUI::GUIPickInfo::PickObjType>();
            switch (data2)
            {
            case GUI::GUIPickInfo::POBJGeometryEdge:
                enablePickSig(GUI::GUIPickInfo::POBJGeometryEdge, GUI::GUIPickInfo::PickMethod::PMSingle);
                break;
            case GUI::GUIPickInfo::POBJGeometryFace:
                enablePickSig(GUI::GUIPickInfo::POBJGeometryFace, GUI::GUIPickInfo::PickMethod::PMSingle);
                break;
            case GUI::GUIPickInfo::POBJGeometrySolid:
                enablePickSig(GUI::GUIPickInfo::POBJGeometrySolid, GUI::GUIPickInfo::PickMethod::PMSingle);
                break;
            default:
                break;
            }
        }
    }

    void GUIGeometryRotateDialog::on_pushButton_OK_clicked()
    {
        QString checkStr = this->checkArgc();//检查参数
        if (checkStr.size() != 0)
        {
            //错误信息汇报
            QMessageBox msgBox;
            msgBox.setIcon(QMessageBox::Warning);  // 设置消息框图标为警告图标
            msgBox.setWindowTitle(tr("warning"));
            msgBox.setText(checkStr);
            msgBox.setStandardButtons(QMessageBox::Ok);  // 设置标准按钮
            msgBox.setDefaultButton(QMessageBox::Ok);  // 设置默认按钮
            int ret = msgBox.exec();//事件循环
            return;
        }

        if (_isCreate)
        {
            if (!this->createObjData())
            {
                return;
            }
        }
        else
        {
            if (!this->editObjData())
                return;
        }
        if (_oper && _obj) {
            _oper->setArgs("objID", _obj->getDataObjectID());
        }
        this->accept();
    }


    void GUIGeometryRotateDialog::on_pushButton_Cancel_clicked()
    {
        _oper->setArgs("objID", -1);
        this->accept();
    }
    void GUIGeometryRotateDialog::on_point_1_pick_clicked()
    {
        {
            GraphData::PickedDataProvider* provider = GraphData::PickedDataProvider::getInstance();
            if (provider == nullptr)return;
            //在切换拾取模式后，将清空对3维的操作
            provider->clearPickedData();//清空拾取数据
            //拾取对象 关闭
            //拾取方式 空
            GUI::GUIPickInfoStru pickInfo = GUI::GUIPickInfo::GetPickInfo();
            pickInfo._pickObjType = GUI::GUIPickInfo::PickObjType(GUI::GUIPickInfo::POBJNone);
            pickInfo._pickMethod = GUI::GUIPickInfo::PickMethod(GUI::GUIPickInfo::PickMethod::PMNone);
            //设置拾取方式
            GUI::GUIPickInfo::SetPickInfo(pickInfo);
        }

        //拾取对象 几何点
        //拾取方式 单独数据拾取方式。（点选+追加拾取）    
        //获取拾取器，绑定拾取结束信号
        GraphData::PickedDataProvider* pickProvider = GraphData::PickedDataProvider::getInstance();
        //清除拾取对象所有的连接
        if (pickProvider != nullptr)
        {
            QObject::disconnect(pickProvider, SIGNAL(sig_pickedOver()), nullptr, nullptr);
            connect(pickProvider, &GraphData::PickedDataProvider::sig_pickedOver, this, &GUIGeometryRotateDialog::OnPickPoint1);
        }
        GUI::GUIPickInfoStru pickInfo = GUI::GUIPickInfo::GetPickInfo();
        pickInfo._pickObjType = GUI::GUIPickInfo::PickObjType(GUI::GUIPickInfo::POBJGeometryVert);
        pickInfo._pickMethod = GUI::GUIPickInfo::PickMethod(GUI::GUIPickInfo::PickMethod::PMSingle);
        //设置拾取方式
        GUI::GUIPickInfo::SetPickInfo(pickInfo);
    }
    void GUIGeometryRotateDialog::on_point_2_pick_clicked()
    {
        {
            GraphData::PickedDataProvider* provider = GraphData::PickedDataProvider::getInstance();
            if (provider == nullptr)return;
            //在切换拾取模式后，将清空对3维的操作
            provider->clearPickedData();//清空拾取数据
            //拾取对象 关闭
            //拾取方式 空
            GUI::GUIPickInfoStru pickInfo = GUI::GUIPickInfo::GetPickInfo();
            pickInfo._pickObjType = GUI::GUIPickInfo::PickObjType(GUI::GUIPickInfo::POBJNone);
            pickInfo._pickMethod = GUI::GUIPickInfo::PickMethod(GUI::GUIPickInfo::PickMethod::PMNone);
            //设置拾取方式
            GUI::GUIPickInfo::SetPickInfo(pickInfo);
        }

        //拾取对象 几何点
        //拾取方式 单独数据拾取方式。（点选+追加拾取）
        //获取拾取器，绑定拾取结束信号
        GraphData::PickedDataProvider* pickProvider = GraphData::PickedDataProvider::getInstance();
        //清除拾取对象所有的连接
        if (pickProvider != nullptr)
        {
            QObject::disconnect(pickProvider, SIGNAL(sig_pickedOver()), nullptr, nullptr);
            connect(pickProvider, &GraphData::PickedDataProvider::sig_pickedOver, this, &GUIGeometryRotateDialog::OnPickPoint2);
        }
        GUI::GUIPickInfoStru pickInfo = GUI::GUIPickInfo::GetPickInfo();
        pickInfo._pickObjType = GUI::GUIPickInfo::PickObjType(GUI::GUIPickInfo::POBJGeometryVert);
        pickInfo._pickMethod = GUI::GUIPickInfo::PickMethod(GUI::GUIPickInfo::PickMethod::PMSingle);
        //设置拾取方式
        GUI::GUIPickInfo::SetPickInfo(pickInfo);
    }
    std::array<double, 3> GUIGeometryRotateDialog::getPointXYZ(int id)
    {
        std::array<double, 3> xyz = { -1,-1,-1 };

        Interface::FITKInterfaceGeometryFactory*factory = Interface::FITKInterfaceGeometryFactory::getInstance();
        if (factory == nullptr)
        {
            return xyz;
        }
        Interface::FITKAbstractGeomToolsCreator*createor = factory->getGeomToolsCreator();
        if (createor == nullptr)
        {
            return{ 0.0,0.0,0.0 };
        }

        Interface::FITKAbstractGeomPointTool *pointTool = createor->createPointTool();
        if (pointTool == nullptr)
        {
            return{ 0.0,0.0,0.0 };
        }
        double PointArray[3];
        pointTool->getXYZ(id, PointArray);

        xyz.at(0) = PointArray[0];
        xyz.at(1) = PointArray[1];
        xyz.at(2) = PointArray[2];
        return xyz;
    }
    QString GUIGeometryRotateDialog::checkArgc()
    {
        //是否未选择
        if (m_pick_num == 0)
        {
            return tr("No pick");
        }

        //是否是错误的值
        bool todoubleStatus = false;
        double x = _ui->lineEdit_X->text().toDouble(&todoubleStatus);
        if (todoubleStatus == false)return tr("Illegal axis starting value X");//非法的 轴线起点
        double y = _ui->lineEdit_Y->text().toDouble(&todoubleStatus);
        if (todoubleStatus == false)return tr("Illegal axis starting value Y");
        double z = _ui->lineEdit_Z->text().toDouble(&todoubleStatus);
        if (todoubleStatus == false)return tr("Illegal axis starting value Z");

        double x2 = _ui->lineEdit_X_2->text().toDouble(&todoubleStatus);
        if (todoubleStatus == false)return tr("Illegal axis end value X");//非法的 轴线终点
        double y2 = _ui->lineEdit_Y_2->text().toDouble(&todoubleStatus);
        if (todoubleStatus == false)return tr("Illegal axis end value Y");
        double z2 = _ui->lineEdit_Z_2->text().toDouble(&todoubleStatus);
        if (todoubleStatus == false)return tr("Illegal axis end value Z");

        //是否轴线起点和终点是一样的
        if (x == x2 && y == y2 && z == z2)
        {
            return tr("Same starting point and ending point");//相同的起点终点
        }


        //检查如果是线旋转，被旋转的线的起点和终点不能和轴线的起点终点一致，因为这样没意义，可能导致未定义行为
        //该判断后续在几何引擎中进行实现


        //旋转角度
        double Value = _ui->lineEdit_Value->text().toDouble(&todoubleStatus);
        if (todoubleStatus == false)
        {
            return tr("Illegal value Value");
        }
        if (Value == 0.0)
        {
            return tr("Value Cannot be 0");
        }
        return "";
    }

}